package cn.edu.zzuli.linkedlist;

public class DoubleLinkListDemo {

    public static void main(String[] args) {
        DoubleLinkList list = new DoubleLinkList();

        Node node1 = new Node(1, "宋江", "及时雨");
        Node node2 = new Node(2, "卢俊义", "玉麒麟");
        Node node3 = new Node(3, "吴用", "智多星");
        Node node4 = new Node(4, "吴用", "智多星");

        list.addByOrder(node4);
        list.addByOrder(node1);
        list.addByOrder(node2);
        list.addByOrder(node3);
        list.list();
        // System.out.println();

        // list.update(new Node(3,"吴用1","智多星"));
        // list.list();
        // System.out.println();

        // list.delete(node3);
        // list.list();

    }
}

class DoubleLinkList {
    private Node head = new Node(0, "", "");

    // 遍历双向链表
    public void list() {
        if (head.next == null) {
            System.out.println("当前链表为空");
            return;
        }

        // 这里我们不需要输出头节点，所以我们可以直接让辅助指针指向第一个节点
        Node temp = head.next;

        while (true) {

            // 这里因为我们要输出最后一个元素，所以不能 判断 temp.next == null
            if (temp == null) {
                break;
            }

            System.out.println(temp);
            temp = temp.next;
        }

    }

    // 向双向链表中添加节点
    // 向链表中添加新元素
    public void add(Node node) {

        // 用一个临时的辅助指针来代替 头指针进行遍历
        Node temp = head;

        // 循环遍历到最后一个节点
        while (true) {
            // 如果temp.next == null,说明当前节点为最后一个节点
            if (temp.next == null) {
                break;
            }

            // temp 指针后移，指向下一个节点
            temp = temp.next;

        }

        // 将最后一个节点 next指向新的元素
        temp.next = node;
        // 将新节点的 pre 指向前一个节点
        node.pre = temp;
    }

    public void addByOrder(Node node) {

        // 用一个临时的辅助指针来代替 头指针进行遍历
        Node temp = head;

        boolean flag = false;

        // 循环遍历到最后一个节点
        while (true) {
            // 如果temp.next == null,说明当前节点为最后一个节点
            if (temp.next == null) {
                break;
            }

            if (node.no < temp.no) {
                flag = true;
                break;
            }

            // temp 指针后移，指向下一个节点
            temp = temp.next;

        }

        if (flag == false && node.no > temp.no) {
            // 将最后一个节点 next指向新的元素
            temp.next = node;
            // 将新节点的 pre 指向前一个节点
            node.pre = temp;
        } else {
            temp.pre.next = node;
            node.pre = temp.pre;

            node.next = temp;
            temp.pre = node;
        }

    }

    // 根据节点的 no进行修改
    public void update(Node node) {
        if (head.next == null) {
            System.out.println("链表为空");
            return;
        }

        Node temp = head.next;

        // 用来判断是否找到 要修改节点
        boolean flag = false;
        // 找到需要修改的节点
        while (true) {

            if (temp == null) {
                // 已经遍历完成
                break;
            }

            if (temp.no == node.no) {
                // 找到该节点
                flag = true;
                break;
            }

            temp = temp.next;

        }

        if (flag) {
            temp.name = node.name;
            temp.nickName = node.nickName;
        } else {
            System.out.println("没有找到编号为" + node.no + "节点");
        }

    }

    // 删除一个节点
    public void delete(Node node) {
        if (head.next == null) {
            System.out.println("链表为空");
            return;
        }

        Node temp = head.next;
        boolean flag = false;

        while (true) {

            // 关于这里是 temp == null
            // 还是 temp.next == null
            // 关键看你需不需要对最后一个节点参与循环
            // temp 是参与循环， temp.next 不参与
            if (temp == null) {
                break;
            }

            if (temp.no == node.no) {
                // 找到该节点，不必像单链表那样找到前一个节点
                flag = true;
                break;
            }

            temp = temp.next;

        }

        if (flag) {
            temp.pre.next = temp.next;
            // 如果不判断的话，当temp是最后一个节点时，会报空指针异常
            if (temp.next != null) {
                temp.next.pre = temp.pre;
            }

        } else {
            System.out.println("没有找到编号为" + node.no + "节点");
        }
    }
}

class Node {
    int no;
    String name;
    String nickName;
    // 指向前一个节点
    Node pre;
    // 指向下一个节点
    Node next;

    public Node(int no, String name, String nickName) {
        this.no = no;
        this.name = name;
        this.nickName = nickName;
    }

    @Override
    public String toString() {
        return "[HeroNode no=" + no + ", name=" + name + ", nickName=" + nickName + "]";
    }

}